/*-+-*****************************************************************************
 Copyright (C) 2009-2012 Oceanside Software Corporation (R)
 Dallas, Texas

 Author       : Jason T. Brower
 Purpose      : This file is part of a point-of-sale software package
                originally written for Table-Service Restaurants.
              
 Date         : July 8th of 2012
              
 History      : The application that this software file belongs to was 
                written over a 3-Year period.  The first version was written
                in C# .Net 3.5 using Windows Forms.  Being new to .Net at
                the time, I soon learned of Windows Presentation Foundation,
                liked the graphics capabilities and databinding so I
                migrated to WPF.  When the .Net 4.0 framework was released
                the application was migrated from 3.5 to 4.0. Now today,
                .Net 4.5 RC is out and I was already in process of migrating
                before I made this public.
                
Excuse Me     : Please excuse the coding style, it is not representative of
                my typical work.  During the three years I was under a very
                tight budget, constantly running out of funding and was 
                working 18 hour days hyped up on 5-Hour Energy.  The 
                design is not textbook.  It is monolythic because of
                previous issues I will not get into.  There are few comments
                in the code and the ones that are there may be incorrect.
                
What it is not: This is not the exact version that I took through PA-DSS 2.0
                nor is it the exact version running at my customer sites.
                I removed some details for security purposes including some
                encryption algorithms.  The reporting was removed because
                I was including a third party library that cannot be 
                published with this Open Source.
                
What it is    : This application has been running at high volume restaraunts
                for over a year.  It never freezes, crashes or does anything
                unexpected.  So long as it is built, installed and configured
                correctly, it is a strong system that we can all enhance.

Contact       : Please note that I can no longer work for free.  However, you
                can reach me at information@oceansidesw.com.                                                      

*********************************************************************************/
using System;
using System.ComponentModel;
using System.Windows.Controls;
using System.Windows.Media;
using System.IO;
using System.Windows.Media.Imaging;


namespace Oceanside
{
    /// <summary>
    /// Interaction logic for ScreenSaver.xaml
    /// </summary>
    public partial class ScreenSaver : PosWindow
    {
        /// <summary>
        /// 
        /// </summary>
        static BackgroundWorker worker;
        public delegate void UpdateLocationDelegate(double xRate, double yRate);
        public delegate void ScreenSaverExceptionDelegateType(Exception e);
        public static ScreenSaverExceptionDelegateType ScreenSaverExceptionDelegate_NOTHROW = null;

        private static System.Action prepareForScreenChangeAction;
        public static System.Action PrepareForScreenChangeAction
        {
            get { return prepareForScreenChangeAction; }
            set { prepareForScreenChangeAction = value; }
        }


        /// <summary>
        /// 
        /// </summary>
        public override void PrepareForScreenChange()
        {
            PrepareForScreenChangeAction();
        }

        /// <summary>
        /// 
        /// </summary>
        private enum DIRECTION
        {
            UP,
            DOWN
        }

        /// <summary>
        /// 
        /// </summary>
        private static double xRate = 0.0;
        private static double yRate = 0.0;
        private static DIRECTION xDirection = DIRECTION.DOWN;
        private static DIRECTION yDirection = DIRECTION.DOWN;
        private static double xLocation = 0.0;
        private static double yLocation = 0.0;
        private static bool PlateHitTheWall = false;

        /// <summary>
        /// 
        /// </summary>
        private static double imgWidth = 115.0;
        private static double imgHeight = 122.0;
        private static double windowWidth = 0.0;
        private static double windowHeight = 0.0;

        private static RotateTransform rotateTransform = new RotateTransform();
        private static Random random = new Random();

        /// <summary>
        /// 
        /// </summary>
        private static bool UpdateDirection()
        {
            bool didHit = false;
            if ((xLocation + imgWidth) > windowWidth)
            {
                xDirection = DIRECTION.DOWN;

                if (yDirection == DIRECTION.DOWN)
                {
                    yDirection = DIRECTION.UP;
                }
                else
                {
                    yDirection = DIRECTION.DOWN;
                }
                yRate = random.NextDouble();
                xRate = random.NextDouble();
                didHit = true;
            }
            else if (xLocation < 0)
            {
                xDirection = DIRECTION.UP;

                if (yDirection == DIRECTION.DOWN)
                {
                    yDirection = DIRECTION.UP;
                }
                else
                {
                    yDirection = DIRECTION.DOWN;
                }
                yRate = random.NextDouble();
                xRate = random.NextDouble();
                didHit = true;
            }

            if ((yLocation + imgHeight) > windowHeight)
            {
                yDirection = DIRECTION.DOWN;

                if (xDirection == DIRECTION.DOWN)
                {
                    xDirection = DIRECTION.UP;
                }
                else
                {
                    xDirection = DIRECTION.DOWN;
                }
                yRate = random.NextDouble();
                xRate = random.NextDouble();
                didHit = true;
            }
            else if (yLocation < 0)
            {
                yDirection = DIRECTION.UP;
                if (xDirection == DIRECTION.DOWN)
                {
                    xDirection = DIRECTION.UP;
                }
                else
                {
                    xDirection = DIRECTION.DOWN;
                }
                yRate = random.NextDouble();
                xRate = random.NextDouble();
                didHit = true;
            }
            return didHit;
        }

        /// <summary>
        /// 
        /// </summary>
        private static void InitStatics()
        {
            xRate = 0.0;
            yRate = 0.0;
            xDirection = DIRECTION.DOWN;
            yDirection = DIRECTION.DOWN;
            xLocation = 0.0;
            yLocation = 0.0;
            PlateHitTheWall = false;

            imgWidth = singleton.imageFloatingLogo.Width;
            imgHeight = singleton.imageFloatingLogo.Height;
            windowWidth = 0.0;
            windowHeight = 0.0;

            rotateTransform = new RotateTransform();
            random = new Random();

            rotateTransform.CenterX = imgWidth / 2.0;
            rotateTransform.CenterY = imgHeight / 2.0;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param Name="seconds"></param>
        /// <param Name="hideCancel"></param>
        /// <param Name="title"></param>
        /// <param Name="mesg"></param>
        /// <param Name="del"></param>
        /// <param Name="top"></param>
        /// <param Name="left"></param>
        private ScreenSaver()
            : base()
        {
            InitializeComponent();
            this.SizeChanged += new System.Windows.SizeChangedEventHandler(ScreenSaver_SizeChanged);

            try
            {
                if (Constants.IsCustomBrandedLicense)
                {
                    if (File.Exists("C:\\loginlogo.png"))
                    {
                        Uri source = new Uri("C:\\loginlogo.png", UriKind.Absolute);
                        imageCanvas.Children.Remove(imageFloatingLogo);
                        imageFloatingLogo = new Image();
                        imageFloatingLogo.Source = new BitmapImage(source);
                        imageCanvas.Children.Add(imageFloatingLogo);
                    }
                }
            }
            catch (Exception e)
            {
                Logging.LogException(e);
            }

            windowHeight = this.Height;
            windowWidth = this.Width;
            imageFloatingLogo.RenderTransform = rotateTransform;
            this.Height = PosWindow.MainPosWindow.Height;
            this.Width = PosWindow.MainPosWindow.Width;
        }

        void ScreenSaver_SizeChanged(object sender, System.Windows.SizeChangedEventArgs e)
        {
            windowHeight = this.Height;
            windowWidth = this.Width;
        }

        static ScreenSaver()
        {
            singleton = new ScreenSaver();
            InitStatics();
        }

        static ScreenSaver singleton = null;

        /// <summary>
        /// 
        /// </summary>
        private static void Initialize()
        {
            try
            {
                ///Get our DispatcherObj
                System.Windows.Threading.Dispatcher pdDispatcher = Constants.MainDispatcher;

                ///Create our background worker and support cancellation
                worker = new BackgroundWorker();
                worker.WorkerSupportsCancellation = true;

                xRate = random.NextDouble();
                yRate = random.NextDouble();

                xLocation = (double)singleton.imageCanvas.GetValue(Canvas.LeftProperty);
                yLocation = (double)singleton.imageCanvas.GetValue(Canvas.TopProperty);

                worker.DoWork += delegate(object s, DoWorkEventArgs args)
                {
                    while (!worker.CancellationPending)
                    {
                        try
                        {
                            System.Threading.Thread.Sleep(50);

                            ///Create a new delegate for updating our progress text
                            UpdateLocationDelegate update = new UpdateLocationDelegate(UpdateImageLocation_NOTHROW);

                            //Invoke the DispatcherObj and pass the percentage and max record count
                            if (xDirection == DIRECTION.UP)
                            {
                                xLocation += xRate;
                            }
                            else
                            {
                                xLocation -= xRate;
                            }

                            if (yDirection == DIRECTION.UP)
                            {
                                yLocation += yRate;
                            }
                            else
                            {
                                yLocation -= yRate;
                            }
                            PlateHitTheWall = UpdateDirection();
                            pdDispatcher.BeginInvoke(update, xLocation, yLocation);
                        }
                        catch (Exception e)
                        {
                            Logging.LogException(e);
                            Constants.MainDispatcher.Invoke(ScreenSaverExceptionDelegate_NOTHROW, e);
                        }
                    }
                    args.Cancel = true;
                };
            }
            catch (Exception ex)
            {
                Logging.LogException(ex);
                Constants.MainDispatcher.Invoke(ScreenSaverExceptionDelegate_NOTHROW, ex);
            }
        }

        /// <summary>
        /// Our delegate used for updating the UI
        /// </summary>
        /// <param Name="percentage"></param>
        /// <param Name="recordCount"></param>
        public static void UpdateImageLocation_NOTHROW(double xLoc, double yLoc)
        {
            try
            {
                singleton.imageCanvas.SetValue(Canvas.LeftProperty, xLoc);
                singleton.imageCanvas.SetValue(Canvas.TopProperty, yLoc);
                if (PlateHitTheWall)
                {
                    rotateTransform.Angle += 20;
                }
            }
            catch (System.Exception exc)
            {
                Constants.ErrorDispatcher.Notify(Error.EType.E_SCREENSAVER_UPDATE_IMAGE_LOCATION, exc);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param Name="sender"></param>
        /// <param Name="e"></param>
        public static void KillAnimation()
        {
            try
            {
                ///Cancel the process
                if (worker != null)
                {
                    worker.CancelAsync();
                    worker.Dispose();
                }
            }
            catch (Exception e)
            {
                Logging.LogException(e);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public static void Animate()
        {
            Initialize();

            try
            {
                worker.RunWorkerAsync();
            }
            catch (Exception e)
            {
                Logging.LogException(e);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public static void Show()
        {
            SwitchWindowDelegate_NOTHROW(singleton);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="o"></param>
        public static void AssignDataContext(object o)
        {
            singleton.DataContext = o;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="tc"></param>
        public static void AddInstanceToTabControl(ref TabControl tc)
        {
            tc.Items.Add(singleton);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="index"></param>
        public static void SetTabIndex(int index)
        {
            singleton.MyTabIndex = index;
        }

#if _TESTMODE
        /// <summary>
        /// The following two are used for test automation.
        /// </summary>
        public delegate void UpdateScreenSaverTimeoutDelType();
        public static UpdateScreenSaverTimeoutDelType UpdateScreenSaverTimeoutDelegate;
#endif

    }
}
